package modbus

import (
	"encoding/binary"
	"errors"
	"time"
)

// =============================================================================
// 网关协议服务端功能码处理器
// =============================================================================

// funcGatewayReadDataRecords 功能码0x50 - 读数据记录
func funcGatewayReadDataRecords(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 6 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	timestamp := binary.BigEndian.Uint32(data[0:4])
	recordCount := binary.BigEndian.Uint16(data[4:6])

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 处理数据对齐请求（记录条数=1）
	if recordCount == 1 {
		// 数据对齐模式，返回对齐时间戳
		alignedTimestamp := store.GetLatestTimestamp()
		if timestamp != 0 {
			// 如果提供了时间戳，进行验证
			alignedTimestamp = timestamp
		}

		response := make([]byte, 7)
		binary.BigEndian.PutUint16(response[0:2], 1)                // 记录条数
		response[2] = 4                                             // 单记录字节数
		binary.BigEndian.PutUint32(response[3:7], alignedTimestamp) // 对齐时间戳
		return response, nil
	}

	// 处理批量读取请求（记录条数=32）
	if recordCount == 32 {
		var records []*DataRecord
		if timestamp == 0 {
			// 读取最新的32条记录
			allRecords := store.GetRecords()
			start := len(allRecords) - 32
			if start < 0 {
				start = 0
			}
			records = allRecords[start:]
		} else {
			// 读取指定时间之后的记录
			records = store.GetRecordsFromTime(timestamp)
		}

		// 确保有32条记录，不足的用空记录填充
		responseRecords := make([]*DataRecord, 32)
		for i := 0; i < 32; i++ {
			if i < len(records) {
				responseRecords[i] = records[i]
			} else {
				// 创建空记录
				responseRecords[i] = &DataRecord{
					Timestamp: uint32(time.Now().Unix()),
				}
			}
		}

		// 构造响应
		response := make([]byte, 3+512)               // 3字节头部 + 512字节数据
		binary.BigEndian.PutUint16(response[0:2], 32) // 记录条数
		response[2] = 16                              // 单记录字节数

		// 填充数据记录
		offset := 3
		for _, record := range responseRecords {
			recordBytes := record.ToBytes()
			copy(response[offset:offset+16], recordBytes)
			offset += 16
		}

		return response, nil
	}

	return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
}

// funcGatewayReadCurrentData 功能码0x51 - 读当前数据
func funcGatewayReadCurrentData(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 6 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	recordCount := binary.BigEndian.Uint16(data[4:6])
	if recordCount != 1 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 获取当前数据
	currentData := store.GetCurrentData()
	if currentData == nil {
		// 如果没有当前数据，创建默认数据
		currentData = &DataRecord{
			Pressure:         0.0,
			PressureUnit:     PressureUnitKPa,
			BatteryLevel:     100,
			ConnectionStatus: 1,
			SignalLevel:      5,
			Timestamp:        uint32(time.Now().Unix()),
		}
	}

	// 构造响应
	response := make([]byte, 3+16)               // 3字节头部 + 16字节数据
	binary.BigEndian.PutUint16(response[0:2], 1) // 记录条数
	response[2] = 16                             // 单记录字节数

	// 填充当前数据
	recordBytes := currentData.ToBytes()
	copy(response[3:19], recordBytes)

	return response, nil
}

// funcGatewayWriteSubDevParam 功能码0x52 - 写子设备参数
func funcGatewayWriteSubDevParam(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 6 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	paramAddr := binary.BigEndian.Uint16(data[0:2])
	paramValue := binary.BigEndian.Uint32(data[2:6])

	// 验证参数地址范围
	if paramAddr < SubDevParamPressureUnit || paramAddr > SubDevParamZeroReset {
		return nil, &ExceptionError{ExceptionCodeIllegalDataAddress}
	}

	// 验证参数值范围
	if err := validateSubDevParam(paramAddr, paramValue); err != nil {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 设置参数
	store.SetSubDevParam(paramAddr, paramValue)

	// 构造响应（回显请求数据）
	response := make([]byte, 6)
	copy(response, data)
	return response, nil
}

// funcGatewayWriteGWParam 功能码0x53 - 写网关参数
func funcGatewayWriteGWParam(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 6 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	paramAddr := binary.BigEndian.Uint16(data[0:2])
	paramValue := binary.BigEndian.Uint32(data[2:6])

	// 验证参数地址范围
	if paramAddr < GatewayParamTime || paramAddr > GatewayParamBacklightTime {
		return nil, &ExceptionError{ExceptionCodeIllegalDataAddress}
	}

	// 验证参数值范围
	if err := validateGatewayParam(paramAddr, paramValue); err != nil {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 设置参数
	store.SetGatewayParam(paramAddr, paramValue)

	// 构造响应（回显请求数据）
	response := make([]byte, 6)
	copy(response, data)
	return response, nil
}

// funcGatewayReadSubDevParam 功能码0x54 - 读子设备参数
func funcGatewayReadSubDevParam(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 2 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	paramAddr := binary.BigEndian.Uint16(data[0:2])

	// 验证参数地址范围
	if paramAddr < SubDevParamPressureUnit || paramAddr > SubDevParamZeroReset {
		return nil, &ExceptionError{ExceptionCodeIllegalDataAddress}
	}

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 获取参数值
	paramValue, exists := store.GetSubDevParam(paramAddr)
	if !exists {
		return nil, &ExceptionError{ExceptionCodeGatewayReadSubDevError}
	}

	// 构造响应（参数地址 + 参数值）
	response := make([]byte, 6)
	binary.BigEndian.PutUint16(response[0:2], paramAddr)
	binary.BigEndian.PutUint32(response[2:6], paramValue)
	return response, nil
}

// funcGatewayReadGWParam 功能码0x55 - 读网关参数
func funcGatewayReadGWParam(reg *NodeRegister, data []byte) ([]byte, error) {
	// 验证请求数据长度
	if len(data) != 2 {
		return nil, &ExceptionError{ExceptionCodeIllegalDataValue}
	}

	// 解析请求参数
	paramAddr := binary.BigEndian.Uint16(data[0:2])

	// 验证参数地址范围
	if paramAddr < GatewayParamTime || paramAddr > GatewayParamBacklightTime {
		return nil, &ExceptionError{ExceptionCodeIllegalDataAddress}
	}

	// 获取网关数据存储
	store := reg.GetGatewayDataStore()
	if store == nil {
		return nil, &ExceptionError{ExceptionCodeServerDeviceFailure}
	}

	// 获取参数值
	paramValue, exists := store.GetGatewayParam(paramAddr)
	if !exists {
		return nil, &ExceptionError{ExceptionCodeGatewayReadGWError}
	}

	// 构造响应（参数地址 + 参数值）
	response := make([]byte, 6)
	binary.BigEndian.PutUint16(response[0:2], paramAddr)
	binary.BigEndian.PutUint32(response[2:6], paramValue)
	return response, nil
}

// =============================================================================
// 参数验证辅助函数
// =============================================================================

// validateSubDevParam 验证子设备参数
func validateSubDevParam(addr uint16, value uint32) error {
	switch addr {
	case SubDevParamPressureUnit:
		if value < PressureUnitMbar || value > PressureUnitInH2O {
			return errors.New("invalid pressure unit")
		}
	case SubDevParamLCDDecimalPlaces:
		if value > 3 {
			return errors.New("invalid decimal places")
		}
	case SubDevParamTransmitterAddr:
		if value < 1 || value > 64 {
			return errors.New("invalid transmitter address")
		}
	case SubDevParamLanguage:
		if value > 1 {
			return errors.New("invalid language")
		}
	case SubDevParamLCDRotation:
		if value > 3 {
			return errors.New("invalid LCD rotation")
		}
	case SubDevParamLCDDisplayStatus:
		if value > 1 {
			return errors.New("invalid LCD display status")
		}
	case SubDevParamBacklightTime:
		if value > 10 {
			return errors.New("invalid backlight time")
		}
	case SubDevParamDataReportInterval:
		if value < 1 || value > 3600 {
			return errors.New("invalid data report interval")
		}
	case SubDevParamZeroReset:
		if value > 1 {
			return errors.New("invalid zero reset")
		}
	}
	return nil
}

// validateGatewayParam 验证网关参数
func validateGatewayParam(addr uint16, value uint32) error {
	switch addr {
	case GatewayParamTime:
		// Unix时间戳，基本不需要验证
		break
	case GatewayParamRS485Baudrate:
		validBaudrates := []uint32{1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200}
		valid := false
		for _, br := range validBaudrates {
			if value == br {
				valid = true
				break
			}
		}
		if !valid {
			return errors.New("invalid baudrate")
		}
	case GatewayParamRS485Address:
		if value < 65 || value > 247 {
			return errors.New("invalid gateway address")
		}
	case GatewayParamBacklightTime:
		if value > 10 {
			return errors.New("invalid backlight time")
		}
	}
	return nil
}
